/**
 * 
 */
package backend;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import main.Controller;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author Christian
 * 
 * @since 0.15
 * 
 */
public class Xml {
	
	/**
	 * Aktuell genutztes File
	 */
	private File file = null;
	
	/**
	 * DatenController
	 */
	private DatenController dataController = null;
	
	/**
	 * 
	 * @param dataController
	 *            DatenController Nötig da, Controller.getDatenController noch null zurückliefert.
	 */
	public Xml(DatenController dataController) {

		this.dataController = dataController;
		try {
			file = new File("Zauberinfo.xml");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 
	 */
	public Xml() {

	}
	
	/**
	 * Prüfung anhand des Versions tags, ob es sich um eine aktuelle ZauberinfoXmlDatei handelt
	 * 
	 * @param file2
	 *            File das getestet werden soll
	 * @return True wenn die Datei die aktuelle XML Version hat
	 */
	public boolean versionCheck(File file2) {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		Document document;
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(file2);
			NodeList versionsNode = document.getElementsByTagName("Version");
			for (int i = 0; i < versionsNode.getLength(); i++) {
				Node n = versionsNode.item(i);
				String version = n.getAttributes().getNamedItem("XMLVersion").getNodeValue();
				return Controller.getXMLVersion().equals(version);
			}
		} catch (FileNotFoundException e) {
			System.out.println("Datei nicht gefunden");
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return false;
	}
	
	/**
	 * Speichert die Daten ins XML-File
	 * 
	 * @param list
	 *            Liste mit den zu speichernden Varianten
	 */
	public void speichern(ArrayList<TextBausteine> list) {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		Document document;
		try {
			document = factory.newDocumentBuilder().newDocument();
			Element topElement = document.createElement("Zauberinfo");
			document.appendChild(topElement);
			Element versionBereich = document.createElement("Version");
			versionBereich.setAttribute("XMLVersion", Controller.getXMLVersion());
			topElement.appendChild(versionBereich);
			Element textBausteine = document.createElement("TextBausteine");
			topElement.appendChild(textBausteine);
			for (TextBausteine textBaustein : list) {
				Element bausteinArt = document.createElement("BausteinArt");
				bausteinArt.setAttribute("zaubername", textBaustein.getZauberName());
				bausteinArt.setAttribute("repaesentation", textBaustein.getRepaesentation());
				textBausteine.appendChild(bausteinArt);
				for (String string : textBaustein.getData()) {
					Element baustein = document.createElement("Baustein");
					baustein.setAttribute("name", string);
					bausteinArt.appendChild(baustein);
				}
			}
			Element zauberVarianten = document.createElement("Zaubervarianten");
			topElement.appendChild(zauberVarianten);
			for (ZauberVariante variante : Controller.getDatenController()
					.getVariantenByZauberName("Alle", "Alle")) {
				Element zauberVarianteElement = document.createElement("Zaubervariante");
				zauberVarianteElement.setAttribute("name", variante.toString());
				zauberVarianteElement.setAttribute("zaubername", variante.getZauberName());
				zauberVarianteElement.setAttribute("rep", variante.getRepaesentation());
				zauberVarianteElement.setAttribute("kosten", variante.getKosten());
				zauberVarianteElement.setAttribute("wirkungsDauer", variante.getWirkungsDauer());
				zauberVarianteElement.setAttribute("zauberDauer", variante.getZauberDauer());
				zauberVarianteElement.setAttribute("kommentar", variante.getKommentar());
				zauberVarianteElement.setAttribute("anmerkung", variante.getAnmerkung());
				zauberVarianteElement.setAttribute("reichweite", variante.getReichweite());
				zauberVarianten.appendChild(zauberVarianteElement);
			}
			Element einstellungen = document.createElement("Einstellungen");
			topElement.appendChild(einstellungen);
			// jetzt noch in einen Datei Transformieren.
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			DOMSource source = new DOMSource(document);
			StreamResult result = new StreamResult(file);
			transformer.transform(source, result);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Methode zum laden der Informationen aus dem Xml-File in die Varianten-List
	 */
	@SuppressWarnings("unchecked")
	public void laden() {

		if (!versionCheck(file)) {
			file.renameTo(new File("ZauberinfoALT.xml"));
		} else {
			dataController.clearBausteinList();
			ArrayList[] list = xmlLesen(file);
			for (Object variante : list[0]) {
				dataController.addTextbaustein((TextBausteine) variante);
			}
			for (Object variante : list[1]) {
				dataController.addZauberVariante((ZauberVariante) variante);
			}
		}
	}
	
	/**
	 * @param file2
	 *            Fileobject aus dem gelsen werden soll
	 * @return Liste mit den Imporiteren varianten
	 */
	@SuppressWarnings("unchecked")
	public ArrayList[] xmlLesen(File file2) {

		ArrayList[] returnList = new ArrayList[2];
		ArrayList<TextBausteine> listText = new ArrayList<TextBausteine>();
		ArrayList<ZauberVariante> listZauber = new ArrayList<ZauberVariante>();
		returnList[0] = listText;
		returnList[1] = listZauber;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		Document document;
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(file2);
			NodeList zauberVarianten = document.getElementsByTagName("Zaubervariante");
			for (int i = 0; i < zauberVarianten.getLength(); i++) {
				Node n = zauberVarianten.item(i);
				String name = n.getAttributes().getNamedItem("name").getNodeValue();
				String zauberName = n.getAttributes().getNamedItem("zaubername").getNodeValue();
				String rep = n.getAttributes().getNamedItem("rep").getNodeValue();
				String anmerkung = n.getAttributes().getNamedItem("anmerkung").getNodeValue();
				String kosten = n.getAttributes().getNamedItem("kosten").getNodeValue();
				String kommentar = n.getAttributes().getNamedItem("kommentar").getNodeValue();
				String zauberDauer = n.getAttributes().getNamedItem("zauberDauer").getNodeValue();
				String wDauer = n.getAttributes().getNamedItem("wirkungsDauer").getNodeValue();
				String reichweite = n.getAttributes().getNamedItem("reichweite").getNodeValue();
				ZauberVariante newVariante = new ZauberVariante();
				newVariante.setName(name);
				newVariante.setZauberName(zauberName);
				newVariante.setRepaesentation(rep);
				newVariante.setAnmerkung(anmerkung);
				newVariante.setKosten(kosten);
				newVariante.setKommentar(kommentar);
				newVariante.setZauberDauer(zauberDauer);
				newVariante.setWirkungsDauer(wDauer);
				newVariante.setReichweite(reichweite);
				listZauber.add(newVariante);
			}
			NodeList textBausteine = document.getElementsByTagName("BausteinArt");
			for (int i = 0; i < textBausteine.getLength(); i++) {
				Node n = textBausteine.item(i);
				ArrayList<String> stringList = new ArrayList<String>();
				String zauberName = n.getAttributes().getNamedItem("zaubername").getNodeValue();
				String repraesentation = n.getAttributes().getNamedItem("repaesentation")
						.getNodeValue();
				NodeList variantenListe = n.getChildNodes();
				for (int i2 = 0; i2 < variantenListe.getLength(); i2++) {
					Node variante = variantenListe.item(i2);
					if (variante != null && variante.getNodeName().equals("Baustein")) {
						stringList.add(variante.getAttributes().getNamedItem("name")
								.getNodeValue());
					}
				}
				String[] array = new String[stringList.size()];
				for (int j = 0; j < stringList.size(); j++) {
					array[j] = stringList.get(j);
				}
				listText.add(new TextBausteine(array, zauberName, repraesentation));
			}
		} catch (FileNotFoundException e) {
			System.out.println("Datei nicht gefunden");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return returnList;
	}
}
